import numpy
from operator import mul
from .functions import _open_netCDF_file, _close_netCDF_file

# ====================================================================
#
# NetCDFFileArray object
#
# ====================================================================

class NetCDFFileArray(object):
    ''' 
    
'''
    def __init__(self, **kwargs):
        '''
        
**Initialization**

:Parameters:

    _filename : str
        The netCDF file name in normalized, absolute form.

    _ncvar : str
        The netCDF variable name for the data array.

    dtype : numpy.dtype
        The numpy data type of the data array.

    ndim : int
        Number of dimensions in the data array.

    shape : tuple
        The data array's dimension sizes.

    size : int
        Number of elements in the data array.

**Examples**

>>> import netCDF4
>>> import os
>>> nc = netCDF4.Dataset('file.nc', 'r')
>>> v = nc.variable['tas']
>>> a = NetCDFFileArray(_filename=os.path.abspath('file.nc'), _ncvar='tas',
                        dtype=v.dtype, ndim=v.ndim, shape=v.shape, size=v.size)

'''
        for attr, value in kwargs.iteritems():
            setattr(self, attr, value)
    #--- End: def
 
    def __deepcopy__(self, memo):
        '''
Used if copy.deepcopy is called on the variable.

'''
        return self.copy()
    #--- End: def

    def __getitem__(self, indices):
        '''
x.__getitem__(indices) <==> x[indices]

Returns a numpy array.

''' 
        nc = self.open()

        array = nc.variables[self._ncvar][indices]

        # ------------------------------------------------------------
        # Collapse a string valued array into
        # memory. E.g. ['a','b','c'] becomes ['abc']
        # ------------------------------------------------------------
        if array.dtype.kind is 'S':
            if array.ndim > 1:
                strlen = array.shape[-1]
                if strlen > 1:
                    new_shape = array.shape[0:-1]
                    new_size  = long(reduce(mul, new_shape, 1))
                    
                    array = numpy.ma.resize(array, (new_size, strlen))
                    
                    # Make sure everything is ok if data is a masked array
                    try:
                        array.set_fill_value(' ')
                        array = array.filled()
                    except AttributeError:
                        pass
                    
                    array = numpy.ma.array([''.join(x).rstrip() for x in array],
                                           dtype='S%d' % strlen)
                    
                    array = numpy.ma.resize(array, new_shape)
        #--- End: if

        return array
    #--- End: def

    def __str__(self):
        '''
x.__str__() <==> str(x)

'''
        return "%s: %s%s in file '%s'" % (self.__class__.__name__, 
                                          self._ncvar, self.shape,
                                          self._filename)
    #--- End: def
    
    def close(self):
        '''

Close the file containing the data array.

If the file is not open then no action is taken.

:Returns:

    None

**Examples**

>>> a.close()

'''
        _close_netCDF_file(self._filename)
    #--- End: def

    def copy(self):
        '''

Return a deep copy.

Equivalent to ``copy.deepcopy(a)``.

:Returns:

    out :
        A deep copy.

**Examples**

>>> b = a.copy()

'''
        return type(self)(**self.__dict__)
    #--- End: def
    
    def open(self):
        '''

Return the netCDF4.Dataset instance for the file containing the data
array.

:Returns:

    out : netCDF4.Dataset

**Examples**

>>> a.open()

'''
        return _open_netCDF_file(self._filename)
    #--- End: def

#--- End: class
